﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows.Forms;
using NPOI.HSSF.UserModel;
using NPOI.SS.UserModel;
using NPOI.XSSF.UserModel;
using Wlx.LogAnalysis.Application.Controllers;
using Wlx.LogAnalysis.Application.Models;

namespace Wlx.LogAnalysis.Application
{
    public partial class AppForm : Form
    {
        //定义一个文件列表的对象，用于维护应用中的所有文件。
        private readonly List<ImportFileModel> _importFiles = new List<ImportFileModel>();

        //匹配模式：code[空格]measure[空格]Value[空格]Unit[空格]Result[空格]Min[空格]Max[空格]
        private static string Pattern = StringPatternFormatter.FormatLinePattern();

        private readonly List<string> _invalidFiles = new List<string>();
        public AppForm()
        {
            InitializeComponent();
        }

        //触发“导入文件”按钮的事件响应
        private void ImportFileBtn_Click(object sender, EventArgs e)
        {
            //文件选择的弹窗设置
            var fileDialog = new OpenFileDialog
            {
                Multiselect = true,
                Title = @"请选择文件",
                Filter = @"所有文件(*.*)|*.*"
            };
            if (fileDialog.ShowDialog() == DialogResult.OK)
            {
                var count = fileDialog.FileNames.Length; //获得选择的文件的数量
                if (fileDialog.CheckFileExists) //判断文件选择弹窗是否正常，而没有“文件不存在”的警告信息
                {
                    ClearListBox();    //清空之前已选的文件列表
                    //遍历已选的文件，把每个文件的文件名，文件路径信息添加到全局定义的_importFiles对象中，并在应用的列表中显示出来
                    for (var i = 0; i < count; i++)
                    {
                        var name = fileDialog.SafeFileNames[i];
                        var path = fileDialog.FileNames[i];
                        _importFiles.Add(new ImportFileModel(name, path));
                        FileListBox.Items.Add(name);
                    }
                }
            }

            //每次上传后就立马调用ScanFiles方法来处理数据，使文件导出更快。
            var result = Task.Run(async () => await ScanFiles()).Result;
            if (!result)
            {
                foreach (var invalidFile in _invalidFiles)
                {
                    if (FileListBox.Items.Contains(invalidFile))
                    {
                        FileListBox.Items.Remove(invalidFile);
                        var importFile = _importFiles.Find(i => i.Name == invalidFile);
                        _importFiles.Remove(importFile);
                    }
                }
            }
        }

        //触发“清空列表”按钮的事件响应
        private void ClearBoxBtn_Click(object sender, EventArgs e)
        {
            ClearListBox();
        }

        //触发“导出文件”按钮的事件响应
        private void ExportBtn_Click(object sender, EventArgs e)
        {
            var exportDialog = new SaveFileDialog  //导出文件的弹窗设置
            {
                FileName = "Test Result " + DateTime.Now.ToString("yyyyMMddHHmmss"),
                Filter = @"导出Excel(*.xlsx)|*.xlsx"
            };
            if (exportDialog.ShowDialog() == DialogResult.OK)  //确认是否导出
            {
                var filePath = exportDialog.FileName;   //导出的文件路径
                if (File.Exists(filePath))             //判断导出的excel是否已存在，如果存在，会提示文件名存在，无法导出。
                {
                    MessageBox.Show(@"该文件名已存在，请重新导出");
                    return;
                }
                using (var fs = new FileStream(filePath, FileMode.CreateNew, FileAccess.ReadWrite))  //将数据写入文件流中，并生成文件
                {
                    var excel = new XSSFWorkbook();  //初始化一个excel对象
                    ISheet sheet = excel.CreateSheet("Test Result");  //excel新建一个表单
                    WriteDataInSheet(sheet);   //将数据信息写入表单中
                    ISheet listSheet = excel.CreateSheet("List");
                    WriteListInSheet(listSheet);

                    excel.Write(fs);
                }
                MessageBox.Show(@"提示： 创建成功！");
            }
        }

        private void WriteListInSheet(ISheet sheet)
        {
            var emptyRow = sheet.CreateRow(0);
            var titleRow = sheet.CreateRow(1);
            titleRow.CreateCell(0).SetCellValue("Test Item");
            titleRow.CreateCell(1).SetCellValue("Min");
            titleRow.CreateCell(2).SetCellValue("Max");

            var tempList = _importFiles.SelectMany(f => f.KeyValueDic)
                .GroupBy(f => f.Key).Select(f => new { f.Key, f.First().Value }).ToList();
            var index = 2;
            foreach (var record in tempList)
            {
                if (record?.Value?.ValidItem ?? false)
                {
                    var row = sheet.CreateRow(index++);
                    row.CreateCell(0).SetCellValue(record.Key.ToString());
                    row.CreateCell(1).SetCellValue(record.Value.Min.ToString());
                    row.CreateCell(2).SetCellValue(record.Value.Max.ToString());
                }
            }
        }

        //清空之前的选择文件列表
        private void ClearListBox()
        {
            _importFiles.Clear();   //全局的_importFiles对象清空
            FileListBox.Items.Clear();  //文件列表清空
        }

        //扫描，解析选择的所有文件
        private async Task<bool> ScanFiles()
        {
            //通过异步来执行解析所有文件
            var result = await Task.Run(() =>
            {
                _invalidFiles.Clear();
                var regex = new Regex(Pattern, RegexOptions.IgnoreCase);
                //遍历所有的文件
                foreach (var fileModel in _importFiles)
                {
                    //根据文件的后缀名来判断是什么类型的log文件
                    try
                    {
                        RptFileManager.FileAnalysis(fileModel, regex); //调用RptFileManager类的静态方法FileAnalysis来解析文件
                    }
                    catch (Exception ex)
                    {
                        var invalidFile = fileModel.Name;
                        _invalidFiles.Add(invalidFile);
                    }
                }
                if (_invalidFiles.Any())
                {
                    var errorMsg = "解析出错文件(已跳过这些文件)：\n" + string.Join(",", _invalidFiles);
                    MessageBox.Show(errorMsg);
                    return false;
                }

                return true;
            });
            return result;
        }

        //将解析的数据写入excel表单中
        private void WriteDataInSheet(ISheet sheet)
        {
            var emptyRow = sheet.CreateRow(0);
            var titleTextList = _importFiles.SelectMany(f => f.KeyValueDic.Keys).Distinct().ToList();  //根据保存的键值对列表计算最上面一行的标题有哪些
            var titleCount = titleTextList.Count;   //计算标题的个数作为excel的列。
            var titleRow = sheet.CreateRow(1);      //在excel表单上创建第一行
            for (var i = 0; i < titleCount; i++)    //在表单第一行创建单元格，并把标题列表逐个添加到单元格中
            {
                titleRow.CreateCell(i).SetCellValue(titleTextList[i]);
            }

            var fileCount = _importFiles.Count;    //文件的个数，通过这个来判定后面的数据有多少行。
            for (var i = 0; i < fileCount; i++)    //再去遍历文件列表
            {
                var dic = _importFiles[i].KeyValueDic;  //获取保存有“方法名”和“测试值”的键值对列表
                var row = sheet.CreateRow(i + 2);       //在excel表单向下再创建一行
                for (var j = 0; j < titleCount; j++)    //遍历标题个数，也就是列的个数
                {
                    var measure = titleRow.GetCell(j).StringCellValue;  //根据列来获取方法名
                    var rangeModel = dic.ContainsKey(measure) ? dic[measure] : new RangeModel();  //根据方法名在键值对列表中获取“测试值”,如果没有，则为空字符串。
                    row.CreateCell(j).SetCellValue(rangeModel?.Value ?? string.Empty);   //把“测试值”填入新创建的单元格中
                }
            }
        }
    }
}
